import time
import random
import os
import sys
import django
from datetime import datetime, timedelta

import akshare as ak
# 首先添加 Django 环境配置和模型导入

from django.db.models import F
import logging

# 获取自定义日志器（与 settings.py 中的 'app' 对应）
logger = logging.getLogger('app')

from akshare_analysis.ak_code_config import read_futures_config

# 添加项目根目录到 Python 路径并配置 Django 环境
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'gupiao_ananlysis.settings')
# django.setup()

from future_history_app.models import FuturesHistory
from future_history_app.models import FuturesCurrent
from future_history_app.models import ConfigDictionary
from future_history_app.models import AkCodeConfig


def fetch_futures_his_data(ak_code_config, current_date=None):
    """获取指定合约指定日期的行情数据"""
    config_dict = ConfigDictionary.objects.get(dic_key="qihuo_his_pull_all")

    # 如果未指定结束日期，使用今天
    if current_date is None:
        end_date_obj = datetime.now()
    else:
        end_date_obj = datetime.strptime(current_date, "%Y%m%d")
    # 获取当前年的年初日期
    start_date_obj = datetime(end_date_obj.year, 1, 1)

    years_back = 0
    while True:
        if config_dict.dic_value == "True":
            # 第一次循环：获取今年年初到今天的数据
            current_end = end_date_obj - timedelta(days=1)
            current_start = end_date_obj - timedelta(days=1)
        else:
            if years_back == 0:
                # 第一次循环：获取今年年初到今天的数据
                current_end = end_date_obj
                current_start = start_date_obj
            else:
                # 之后的循环：获取完整年度数据（从1月1日到12月31日）
                target_year = end_date_obj.year - years_back
                current_end = datetime(target_year, 12, 31)
                current_start = datetime(target_year, 1, 1)
        # 格式化日期
        start_date_str = current_start.strftime("%Y%m%d")
        end_date_str = current_end.strftime("%Y%m%d")

        try:
            # 获取当天的期货数据
            # 注意：这里将start_date和end_date都设为同一天，只获取单天数据
            df = ak.futures_main_sina(
                symbol=ak_code_config.ak_code,
                start_date=start_date_str,
                end_date=end_date_str
            )
            # 检查是否获取到有效数据
            if df is not None and not df.empty:
                logger.info(
                    f"成功获取 {ak_code_config.ak_code} {start_date_str} 到 {end_date_str} 的数据，共 {len(df)} 条记录")
                save_to_database(ak_code_config, df)
                AkCodeConfig.objects.filter(ak_code=ak_code_config.ak_code).update(
                    update_time=datetime.now(),
                )
            else:
                break
            if config_dict.dic_value == "True":
                break
            time.sleep(random.randint(9, 15))
        except Exception as e:
            logger.info(f"{ak_code_config.ak_code} 数据获取失败: {e}")
            # 不往前推，再重新执行一次
            if "远程主机强迫关闭了一个现有的连接" in str(e):
                continue
            return None
        # 往前推一年
        years_back += 1


def save_to_database(ak_code_config, df):
    """
    使用 FuturesHistory 模型将数据保存到数据库
    """
    # 获取第一行数据（通常只有一行数据）
    for index, row in df[::-1].iterrows():
        # 提取每条记录的日期
        date_int = int(row.get("日期", None).strftime("%Y%m%d"))
        try:
            low_price_his = convert_to_decimal(row.get('最低价', None))
            if low_price_his < 10:
                continue
            # 历史低价
            current_record_current = FuturesCurrent.objects.get(ak_code=ak_code_config.ak_code)

            # 只有当数据多于一条时才更新launch_date
            if len(df) > 1:
                FuturesCurrent.objects.filter(ak_code=ak_code_config.ak_code).update(
                    launch_date=date_int,
                )

            if low_price_his is not None:
                # 更新历史最低价
                if current_record_current.minimum is None or low_price_his < current_record_current.minimum:
                    FuturesCurrent.objects.filter(ak_code=ak_code_config.ak_code).update(
                        minimum=low_price_his,
                        min_date=date_int,
                        current_to_lowest=F('current') / low_price_his,
                    )
                    # 批量更新所有历史记录 minimum 和 current_to_lowest 字段
                    if low_price_his != 0:  # 确保分母不为0
                        FuturesHistory.objects.filter(ak_code=ak_code_config.ak_code).update(
                            minimum=low_price_his,
                            min_date=date_int,
                            current_to_lowest=F('current') / low_price_his,
                            lowest_to_highest=low_price_his / F('highest')
                        )
                    else:
                        FuturesHistory.objects.filter(ak_code=ak_code_config.ak_code).update(
                            minimum=low_price_his,
                            current_to_lowest=None
                        )
                    # 重新获取更新后的记录
                    current_record_current = FuturesCurrent.objects.get(ak_code=ak_code_config.ak_code)

            if low_price_his is not None:
                # 更新历史最高价
                if current_record_current.highest is None or low_price_his > current_record_current.highest:
                    FuturesCurrent.objects.filter(ak_code=ak_code_config.ak_code).update(
                        highest=low_price_his,
                    )
                    FuturesHistory.objects.filter(ak_code=ak_code_config.ak_code).update(
                        highest=low_price_his,
                        lowest_to_highest=F('minimum') / low_price_his,
                    )
                    # 重新获取更新后的记录
                    current_record_current = FuturesCurrent.objects.get(ak_code=ak_code_config.ak_code)

            # 创建 FuturesHistory 实例
            FuturesHistory.objects.update_or_create(
                ak_code=ak_code_config.ak_code,
                trans_date=date_int,
                defaults={
                    "exchange": ak_code_config.exchange,
                    "breed": ak_code_config.breed,
                    "code": ak_code_config.code,
                    "code_complete": ak_code_config.code_complete,
                    "current": low_price_his,  # 收盘价
                    "minimum": current_record_current.minimum,
                    "highest": current_record_current.highest,
                    "min_date": current_record_current.min_date,
                    "current_to_lowest": (
                        float(low_price_his) / float(current_record_current.minimum)
                        if low_price_his is not None and current_record_current.minimum is not None and current_record_current.minimum != 0
                        else None
                    ),
                    "lowest_to_highest": (
                        float(low_price_his) / float(current_record_current.highest)
                        if low_price_his is not None and current_record_current.highest is not None and current_record_current.highest != 0
                        else None
                    )
                }
            )
        except Exception as e:
            logger.info(f"{ak_code_config.ak_code} {date_int} 数据处理失败: {e}")
            continue


# 数据类型转换函数
def convert_to_decimal(value):
    if value is None or value == '' or value == 'None':
        return None
    try:
        # 处理可能包含逗号的数字（如 "5,019"）
        if isinstance(value, str):
            value = value.replace(',', '')
        return float(value)
    except (ValueError, TypeError):
        logger.info(f"无法转换值 {value} 为数值类型")
        return None


if __name__ == "__main__":
    # 测试读取配置
    ak_code_data = read_futures_config()
    for row in ak_code_data:
        # 示例：获取玻璃主力合约数据
        # contract_code = "V0"  # 玻璃主力合约代码
        #
        # # 可以指定起始日期，如 "20250630"，也可以留空使用今天
        fetch_futures_his_data(row, (datetime.now() - timedelta(days=6)).strftime("%Y%m%d"))
